import path from 'path';

import { expect } from '@jest/globals';
import { HvigorLogger } from '@ohos/hvigor';
import execa from 'execa';
import fse from 'fs-extra';

import { getJson5Obj } from '../../../../src/utils/json-util.js';
import { initExecuteCommand, runHvigorAsync } from '../../common/common';
import { commonConfig } from '../../plugins/common-config.js';
import { addOhPackageDps, commonFileOperation, commonJson5Operation, decompressHapAndReadEntries, decompressHarAndReadEntries } from '../../plugins/common-fun';
import {
  AbilityType,
  APIType,
  APIVersion,
  CaseLevel,
  LanguageType,
  ModuleTemplateType,
  RuntimeOSType,
  SDKType,
} from '../../plugins/project-builder/models/constants';
import { Project } from '../../plugins/project-builder/models/project-models';
import { ICaseRecord } from '../../plugins/report-builder/report-models';
import { TestCaseBuilder } from '../../plugins/task-builder/task-case-builder';
import { ProjectBuildOption, TestCaseFun } from '../../plugins/task-builder/test-case';
import { TestTaskOption, TestTaskOptionBuilder } from '../../plugins/task-builder/test-task-option';

const projectBuilderOption: ProjectBuildOption = {
  template: {
    sdk: SDKType.Single,
    runtimeOS: RuntimeOSType.HarmonyOS,
    apiVersion: APIVersion.API10,
    apiType: APIType.STAGE,
    language: LanguageType.ArkTs,
    abilityType: AbilityType.Application,
    entryTemplateType: ModuleTemplateType.EmptyAbility,
  },
  modulesOption: {
    [ModuleTemplateType.SharedLibraryWithC]: 1,
  },
};

/**
 *  1. 修改配置项，确认setBuildOpt()优先级最高
 *  2. 构建hsp包
 *  3. 构建之后检查.so文件是否存在于interface har
 *  4. 构建hap包
 *  5. 检查是否包含正确warn信息
 * @param {Project} project
 * @param {TestTaskOption} taskConfig
 * @param {ICaseRecord} record
 * @return res
 */
const testFun: TestCaseFun = async (project: Project, taskConfig: TestTaskOption, record: ICaseRecord) => {
  const projectRoot = project.projectRootPath();

  // 1. 修改hsp模块的build-profile.json5 的 buildOption 配置信息,增加配置项excludeSoFromInterfaceHar
  // 1.1 多种场景优先级测试，包括工程build-profile.json，模块build-profile.json，api设置
  const libraryPath = project.getModule('shareNativeCLibrary').moduleRootPath();
  const hviforfilePath = path.resolve(projectRoot, 'hvigorfile.ts');

  // 修改工程 build-profile.json5 的 nativeLib 信息
  await commonJson5Operation(path.resolve(projectRoot, 'build-profile.json5'), async (json5) => {
    json5.app.products[0].buildOption = {
      nativeLib: {
        excludeSoFromInterfaceHar: true,
      },
    };
  });
  // 修改hsp模块 build-profile.json5 的 nativeLib 信息
  await commonJson5Operation(path.resolve(libraryPath, 'build-profile.json5'), async (json5) => {
    json5.buildOption.nativeLib = {
      excludeSoFromInterfaceHar: false,
    };
  });
  // 通过api修改模块 build-profile.json5 的 nativeLib 信息
  const apiCode =
    'import { hvigor } from \'@ohos/hvigor\';\nimport { appTasks } from \'@ohos/hvigor-ohos-plugin\';\nimport { OhosHapContext, OhosPluginId } from "@ohos/hvigor-ohos-plugin";\nimport { OhosHspContext, OhosPluginId } from "@ohos/hvigor-ohos-plugin";\nhvigor.nodesEvaluated(() => {\n    hvigor.getRootNode().subNodes(subNode => {\n        const hapContext = subNode.getContext(OhosPluginId.OHOS_HAP_PLUGIN) as OhosHapContext;\n        const hspContext = subNode.getContext(OhosPluginId.OHOS_HSP_PLUGIN) as OhosHspContext;\n        if (hspContext){\n            const buildProfileOpt = hspContext.getBuildProfileOpt();\n            buildProfileOpt.buildOption.nativeLib.excludeSoFromInterfaceHar = true;\n            hspContext.setBuildProfileOpt(buildProfileOpt);\n        }\n    });\n});\nexport default {\n    system: appTasks,\n    plugins:[]\n}';
  fse.writeFileSync(hviforfilePath, apiCode, 'utf-8');
  // 2. 构建 release hsp 包
  const assembleHspCmd = initExecuteCommand({
    mode: 'module',
    module: 'shareNativeCLibrary@default',
    product: 'default',
    tasks: 'assembleHsp',
    buildMode: 'release',
  });
  const assembleHspResult = await runHvigorAsync(projectRoot, assembleHspCmd);
  record.addStep('编译构建 shareNativeCLibrary 模块生成hsp', assembleHspResult);
  expect(assembleHspResult.stdout).toContain('BUILD SUCCESSFUL');

  // 3. 构建成功，检查是否存在output路径,无论配置项是否开启都应该存在interface har
  const outPutPath = path.resolve(libraryPath, 'build', 'default', 'outputs', 'default');
  const interfaceHarName = (await fse.readdir(outPutPath)).filter((item) => item.endsWith('.har'))[0];
  const interfaceHarPath = path.resolve(outPutPath, interfaceHarName);
  expect(fse.existsSync(interfaceHarPath)).toEqual(true);

  // 4. 存在路径，检查是否将interface har中的.so文件去除
  const harFiles = await decompressHarAndReadEntries(path.resolve(outPutPath, interfaceHarName));
  const fileNames = harFiles.map((item) => item[0]);
  const hasLibs = fileNames.some((fileName) => fileName.endsWith('.so'));
  expect(hasLibs).toEqual(false);

  // 5 构建release hap包
  const assembleHapCmd = initExecuteCommand({
    mode: 'module',
    product: 'default',
    tasks: 'assembleHap',
    buildMode: 'release',
  });
  const assembleHapResult = await runHvigorAsync(projectRoot, assembleHapCmd);
  record.addStep('编译构建 entry 模块生成hap', assembleHapResult);
  // 6. 检查警告信息是否包含特定内容
  expect(assembleHapResult.stderr).toContain('excludeSoFromInterfaceHar only applies to HSPs. It is not effective for HAPs.');
};

TestCaseBuilder.builder()
  .caseName('AR20240902146809')
  // eslint-disable-next-line max-len
  .description('hsp打包开启配置项excludeSoFromInterfaceHar')
  .projectBuilderOption(projectBuilderOption)
  .taskConfig(TestTaskOptionBuilder.builder().caseLevel(CaseLevel.DTS).build())
  .testFun(testFun)
  .load();
